package com.tc.zigbee.mt;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.tc.gateway.DeviceManagementListener;
import com.tc.gateway.DeviceManager;
import com.tc.gateway.GatewayEngine;
import com.tc.gateway.GroupManager;
import com.tc.gateway.SceneManager;

import com.tc.gateway.device.GeneralDevice;
import com.tc.gateway.event.AttributeReadEvent;
import com.tc.gateway.event.Event;
import com.tc.gateway.event.EventCenter;
import com.tc.gateway.event.GroupAddRespEvent;
import com.tc.gateway.event.GroupRemoveRespEvent;
import com.tc.gateway.event.RefreshEvent;
import com.tc.gateway.event.ReportEvent;
import com.tc.util.DataUtil;
import com.tc.zigbee.entity.Endpoint;
import com.tc.zigbee.entity.ZigbeeGroup;
import com.tc.zigbee.entity.ZigbeeScene;
import com.tc.zigbee.entity.ZNode;
import com.tc.zigbee.entity.device.ZigbeeDevice;
import com.tc.zigbee.ha.HAConstants;
import com.tc.zigbee.mt.income.ActiveEndpointResponse;
import com.tc.zigbee.mt.income.AfIncomeMessage;
import com.tc.zigbee.mt.income.ComplexDescriptorResponse;
import com.tc.zigbee.mt.income.DeviceAnnounceIndication;
import com.tc.zigbee.mt.income.IeeeResponse;
import com.tc.zigbee.mt.income.IncomeMessage;
import com.tc.zigbee.mt.income.NodeDescriptorResponse;
import com.tc.zigbee.mt.income.PowerDescriptorResponse;
import com.tc.zigbee.mt.income.SimpleDescriptorResponse;
import com.tc.zigbee.mt.request.RequestFactory;
import com.tc.zigbee.zcl.ZclCommandCreator;
import com.tc.zigbee.zcl.ZclConstants;
import com.tc.zigbee.zcl.command.AbstractZclCommand;
import com.tc.zigbee.zcl.command.AddGroupResponse;
import com.tc.zigbee.zcl.command.AttributeRecord;
import com.tc.zigbee.zcl.command.GroupMemberResponse;
import com.tc.zigbee.zcl.command.ReadAttributeResponse;
import com.tc.zigbee.zcl.command.RemoveGroupResponse;
import com.tc.zigbee.zcl.command.SceneMemberResponse;
import com.tc.zigbee.zcl.command.StoreSceneResponse;

public class ZigbeeManager implements MessageListener ,GatewayEngine{
	DeviceManager deviceManager;
	GroupManager groupManager;
	SceneManager sceneManager;
	Collection<DeviceManagementListener> deviceListeners = new ArrayList<DeviceManagementListener>();
	public Endpoint remoteControl;
	public Endpoint configuration;

	public ZigbeeManager() {
		super();
		deviceManager = new ZigbeeDeviceManager(this);
		groupManager = new ZigbeeGroupManager(this);
		sceneManager = new ZigbeeSceneManager(this);
		
		remoteControl = new Endpoint(null, (byte)200, this);
		remoteControl.setProfileId(HAConstants.ZCL_HA_PROFILE_ID);
		remoteControl.setDeviceId(HAConstants.ZCL_HA_DEVICEID_REMOTE_CONTROL);
		remoteControl.setDeviceVersion((byte)0);
		remoteControl.setLatency((byte)0);
		
		remoteControl.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_GEN_BASIC);
		remoteControl.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_GEN_IDENTIFY);
		remoteControl.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_GEN_ON_OFF);
		remoteControl.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL);
		remoteControl.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_GEN_GROUPS);
		remoteControl.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_GEN_SCENES);
		remoteControl.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL);
		remoteControl.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_HVAC_PUMP_CONFIG_CONTROL);
		remoteControl.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_CLOSURES_SHADE_CONFIG);
		remoteControl.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIG);
		remoteControl.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT);
		remoteControl.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_MS_ILLUMINANCE_LEVEL_SENSING_CONFIG);
		remoteControl.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_MS_ILLUMINANCE_MEASUREMENT);
		remoteControl.setNumOutClusters((byte)remoteControl.getOutClusters().size());
		
		
		configuration = new Endpoint(null, (byte)201, this);
		configuration.setProfileId(HAConstants.ZCL_HA_PROFILE_ID);
		configuration.setDeviceId(HAConstants.ZCL_HA_DEVICEID_CONFIGURATIOPN_TOOL);
		configuration.setDeviceVersion((byte)0);
		configuration.setLatency((byte)0);
		
		configuration.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_GEN_BASIC);
		configuration.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_GEN_IDENTIFY);
		
		configuration.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_GEN_GROUPS);
		configuration.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_GEN_SCENES);
		configuration.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_MS_ILLUMINANCE_LEVEL_SENSING_CONFIG);
		configuration.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT);
		configuration.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_MS_PRESSURE_MEASUREMENT);
		configuration.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_MS_FLOW_MEASUREMENT);
		configuration.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_MS_OCCUPANCY_SENSING);
		configuration.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_HVAC_PUMP_CONFIG_CONTROL);
		
		configuration.getOutClusters().add(ZclConstants.ZCL_CLUSTER_ID_CLOSURES_SHADE_CONFIG);
		
		configuration.setNumOutClusters((byte)remoteControl.getOutClusters().size());
		
	}

	

	// int count = 1;
	public Map<Short, ZNode> getNodes() {
		return nodes;
	}

	Map<Short, ZNode> nodes = new HashMap<Short, ZNode>();
	Map<Short, ZigbeeGroup> groups = new HashMap<Short, ZigbeeGroup>();
	Map<Byte, ZigbeeScene> scenes = new HashMap<Byte, ZigbeeScene>();

	Map<String, ZigbeeDevice> devices = new HashMap<String, ZigbeeDevice>();
	
	public Map<Byte, ZigbeeScene> getScenes() {
		return scenes;
	}

	public Map<Short, ZigbeeGroup> getGroups() {
		return groups;
	}

	ZNode getNode(short nwk) {
		for (ZNode n : nodes.values()) {
			if (n.getNwkAddress() == nwk)
				return n;
		}
		return null;
	}
	ZNode getNode(long ieee) {
		for (ZNode n : nodes.values()) {
			if (DataUtil.longValue(n.getIeeeAddress()) == ieee)
				return n;
		}
		return null;
	}
	ZNode getNode(String ieee) {
		for (ZNode n : nodes.values()) {
			if ((DataUtil.hex(n.getIeeeAddress())).equals(ieee) && n.getNwkAddress() != 0)
				return n;
		}
		for (ZNode n : nodes.values()) {
			if ((DataUtil.hex(n.getIeeeAddress())).equals(ieee) )
				return n;
		}
		return null;
	}
	public ZNode coordinator(){
		return nodes.get((short)0);
	}

	public void onMessage(IncomeMessage msg) {
		if (msg instanceof IeeeResponse) {

			IeeeResponse resp = (IeeeResponse) msg;
			long ieee = DataUtil.longValue(resp.getIeeeAddress());
			ZNode node = nodes.get(resp.getNwkAddress());
			if (node == null) {
				node = new ZNode();
			}

			node.setNwkAddress(resp.getNwkAddress());
			node.setIeeeAddress(resp.getIeeeAddress());
			nodes.put(resp.getNwkAddress(), node);
			MtCommand mc = RequestFactory.MtActiveEndpointRequest(node
					.getNwkAddress(), node.getNwkAddress());
			RequestQueue.offer(mc);
			mc = RequestFactory.MtNodeDescRequest(node.getNwkAddress(), node
					.getNwkAddress());
			RequestQueue.offer(mc);
			mc = RequestFactory.MtPowerDescRequest(node.getNwkAddress(), node
					.getNwkAddress());
			RequestQueue.offer(mc);
			mc = RequestFactory.MtComplexDescRequest(node.getNwkAddress(), node
					.getNwkAddress());
			RequestQueue.offer(mc);
			List<Short> accs = resp.getAssocDevices();
			for (short na : accs) {
				mc = RequestFactory.MtIEEEAddrRequest(na, (byte) 0, (byte) 0);
				RequestQueue.offer(mc);

			}
			// if(count == 0)
			updateUT();

		}
		if (msg instanceof NodeDescriptorResponse) {
			NodeDescriptorResponse rsp = (NodeDescriptorResponse) msg;
			ZNode node = getNode(rsp.getNodeDescriptor().nwkAddr);
			if (node == null)
				throw new RuntimeException("zigbee�ڵ㲻���ڣ�");
			node.setNodeDescriptor(rsp.getNodeDescriptor());
		}
		if (msg instanceof PowerDescriptorResponse) {
			PowerDescriptorResponse rsp = (PowerDescriptorResponse) msg;
			ZNode node = getNode(rsp.getPowerDescriptor().nwkAddr);
			if (node == null)
				throw new RuntimeException("zigbee�ڵ㲻���ڣ�");
			node.setPowerDescriptor(rsp.getPowerDescriptor());
		}
		if (msg instanceof ComplexDescriptorResponse) {
			ComplexDescriptorResponse rsp = (ComplexDescriptorResponse) msg;
			ZNode node = getNode(rsp.getComplexDescriptor().nwkAddr);
			if (node == null)
				throw new RuntimeException("zigbee�ڵ㲻���ڣ�");
			node.setComplexDescriptor(rsp.getComplexDescriptor());
		}

		if (msg instanceof ActiveEndpointResponse) {
			ActiveEndpointResponse rsp = (ActiveEndpointResponse) msg;
			ZNode node = getNode(rsp.getNwkAddress());
			if (node == null)
				throw new RuntimeException("zigbee�ڵ㲻���ڣ�");
			for (Byte eid : rsp.getEndpoints()) {
				Endpoint e = node.getEndPoint(eid);
				if(e != null)
					continue;
				node.getActiveEndpoints().add(new Endpoint(node, eid, this));
				MtCommand mc = RequestFactory.MtSimpleDescRequest(node
						.getNwkAddress(), node.getNwkAddress(), eid);
				RequestQueue.offer(mc);
			}
			// if(count == 0)
			updateUT();
		}
		if (msg instanceof DeviceAnnounceIndication) {
			DeviceAnnounceIndication resp = (DeviceAnnounceIndication) msg;

			ZNode node = nodes.get(resp.getNwkAddr());
			if (node == null) {
				node = new ZNode();
			}

			node.setNwkAddress(resp.getNwkAddr());
			node.setIeeeAddress(DataUtil.bytesValue(resp.getIeeeAddr()));
			nodes.put(resp.getNwkAddr(), node);
			MtCommand mc = RequestFactory.MtActiveEndpointRequest(node
					.getNwkAddress(), node.getNwkAddress());
			RequestQueue.offer(mc);
			mc = RequestFactory.MtNodeDescRequest(node.getNwkAddress(), node
					.getNwkAddress());
			RequestQueue.offer(mc);
			mc = RequestFactory.MtPowerDescRequest(node.getNwkAddress(), node
					.getNwkAddress());
			RequestQueue.offer(mc);
			mc = RequestFactory.MtComplexDescRequest(node.getNwkAddress(), node
					.getNwkAddress());
			RequestQueue.offer(mc);
			updateUT();
		}
		if (msg instanceof SimpleDescriptorResponse) {

			SimpleDescriptorResponse resp = (SimpleDescriptorResponse) msg;
			ZNode node = getNode(resp.getNwkAddress());
			if (node == null)
				throw new RuntimeException("zigbee�ڵ㲻���ڣ�");
			Endpoint ep = resp.getEndpoint();
			Endpoint target = node.getEndPoint(ep.getEndpointId());
			if (target == null)
				throw new RuntimeException("endpoint�ڵ㲻���ڣ�");

			target.fill(ep);
			ZigbeeDevice d = target.createDevice();
			if(d != null){
				devices.put(d.getId(), d);
				this.deviceAdded(d);
			}

			if (ep.getInClusters().contains(
					ZclConstants.ZCL_CLUSTER_ID_GEN_GROUPS)) {
				byte[] zclcommand = ZclCommandCreator.getGroupMember((byte) 0);
				MtCommand mc = RequestFactory.MtAfDataRequest((byte) 2,
						(byte) node.getNwkAddress(),

						(byte) ep.getEndpointId(),
						(byte) remoteControl.getEndpointId(),
						ZclConstants.ZCL_CLUSTER_ID_GEN_GROUPS, (byte) 0,
						(byte) 0, (byte) 2, (byte) zclcommand.length,
						zclcommand);
				RequestQueue.offer(mc);
			}

			// if(count == 0)
			updateUT();
		}

		if (msg instanceof AfIncomeMessage) {
			AfIncomeMessage am = (AfIncomeMessage) msg;
			AbstractZclCommand ac = am.getParsedCommand();
			if (ac != null) {
				if (ac instanceof com.tc.zigbee.zcl.command.Report) {
					com.tc.zigbee.zcl.command.Report ar = (com.tc.zigbee.zcl.command.Report)ac;
					short addr = am.getSrcAddr();
					ZNode node = nodes.get(addr);
					if (node == null){
						return;
	//					throw new RuntimeException("");
					}
					Endpoint ep = node.getEndPoint(am.getSrcEndpoint());
					if(ep == null)
						return;
					for (AttributeRecord dv : ar.getAttributes()) {
						if (dv.status == 0)
							ep.setAttribute(am.getClusterId(), dv.attributeId,
									dv.value);
					}
					ReportEvent e = new ReportEvent();
					e.setIeeeAddress(node.getIeeeAddress());
					e.setEndpoint(am.getSrcEndpoint());
					e.setCluster(am.getClusterId());

					EventCenter.getInstance().fireEvent(e);
				}
				if (ac instanceof ReadAttributeResponse) {

					ReadAttributeResponse ar = (ReadAttributeResponse) ac;

					short addr = am.getSrcAddr();
					ZNode node = nodes.get(addr);
					if (node == null)
						throw new RuntimeException("");
					Endpoint ep = node.getEndPoint(am.getSrcEndpoint());
					for (AttributeRecord dv : ar.getAttributes()) {
						if (dv.status == 0)
							ep.setAttribute(am.getClusterId(), dv.attributeId,
									dv.value);
					}
					AttributeReadEvent e = new AttributeReadEvent();
					e.setIeeeAddress(node.getIeeeAddress());
					e.setEndpoint(am.getSrcEndpoint());
					e.setCluster(am.getClusterId());

					EventCenter.getInstance().fireEvent(e);
				}
				if (ac instanceof AddGroupResponse) {
					AddGroupResponse ar = (AddGroupResponse) ac;
					if (ar.getStatus() != 0) {
						System.out.println("");
						return;
					}
					short addr = am.getSrcAddr();
					ZNode node = nodes.get(addr);
					if (node == null)
						throw new RuntimeException("");
					Endpoint ep = node.getEndPoint(am.getSrcEndpoint());
					ZigbeeGroup g = this.groups.get(ar.getGroupId());
					if(g == null){
						g = new ZigbeeGroup();
						g.setId(ar.getGroupId());
						this.groups.put(g.getId(), g);
					}
					if(!g.getMembers().contains(ep.getDevice()))
						g.getMembers().add(ep.getDevice());

					GroupAddRespEvent e = new GroupAddRespEvent();
					e.setAddress(am.getSrcAddr());
					e.setEndpoint(am.getSrcEndpoint());
					//e.setResp(ar);

					EventCenter.getInstance().fireEvent(e);
				}
				if (ac instanceof RemoveGroupResponse) {
					RemoveGroupResponse ar = (RemoveGroupResponse) ac;
					short addr = am.getSrcAddr();
					ZNode node = nodes.get(addr);
					if (node == null)
						throw new RuntimeException("");
					Endpoint ep = node.getEndPoint(am.getSrcEndpoint());
					ZigbeeGroup g = this.groups.get(ar.getGroupId());
					if (g != null) {
						g.getMembers().remove(ep.getDevice());
						GroupRemoveRespEvent e = new GroupRemoveRespEvent();
						e.setAddress(am.getSrcAddr());
						e.setEndpoint(am.getSrcEndpoint());
						//e.setResp(ar);

						EventCenter.getInstance().fireEvent(e);
					}
				}
				if (ac instanceof SceneMemberResponse) {
					SceneMemberResponse ar = (SceneMemberResponse) ac;
					short addr = am.getSrcAddr();
					ZNode node = nodes.get(addr);
					if (node == null)
						throw new RuntimeException("");
					Endpoint ep = node.getEndPoint(am.getSrcEndpoint());
					ZigbeeGroup g = this.groups.get(ar.getGroupId());
					if (g != null) {
						for (byte sid : ar.getMembership()) {
							ZigbeeScene scene = this.scenes.get(sid);
							if (scene == null) {
								scene = new ZigbeeScene();
								scene.setParent(g);
								scene.setGroup(g.getId());
								scene.setScene(sid);
								scenes.put(sid, scene);

							}

						}
					}
					updateUT();
				}
				if (ac instanceof StoreSceneResponse) {

					StoreSceneResponse ar = (StoreSceneResponse) ac;
					if (ar.getStatus() != 0) {
						System.out.println("�����洢ʧ��,������:" + "0x"
								+ Integer.toHexString(ar.getStatus() & 0xff));
						return;
					}
					short addr = am.getSrcAddr();
					ZNode node = nodes.get(addr);
					if (node == null)
						throw new RuntimeException("");

					ZigbeeGroup g = this.groups.get(ar.getGroupId());
					ZigbeeScene scene = new ZigbeeScene();
					scene.setGroup(ar.getGroupId());
					scene.setParent(g);
					scene.setScene(ar.getSceneId());
					scenes.put(scene.getScene(), scene);
					updateUT();
				}
				if (ac instanceof GroupMemberResponse) {
					GroupMemberResponse ar = (GroupMemberResponse) ac;
					short addr = am.getSrcAddr();
					ZNode node = nodes.get(addr);
					if (node == null)
						throw new RuntimeException("");
					Endpoint ep = node.getEndPoint(am.getSrcEndpoint());

					for (Short gid : ar.getMembership()) {
						ZigbeeGroup g = this.groups.get(gid);
						if (g == null) {
							g = new ZigbeeGroup();
							g.setId(gid);
							this.groups.put(gid, g);
							if (ep.getInClusters().contains(
									ZclConstants.ZCL_CLUSTER_ID_GEN_SCENES)) {
								byte[] zclcommand = ZclCommandCreator
										.sceneMembership((byte) 0, gid);
								MtCommand mc = RequestFactory.MtAfDataRequest(
										(byte) 2, node.getNwkAddress(),
										(byte) ep.getEndpointId(),
										(byte) remoteControl
												.getEndpointId(),
										ZclConstants.ZCL_CLUSTER_ID_GEN_SCENES,
										(byte) 0, (byte) 0, (byte) 2,
										(byte) zclcommand.length, zclcommand);
								RequestQueue.offer(mc);
							}
						}
						if(!g.getMembers().contains(ep))
							g.getMembers().add(ep.getDevice());
					}
					updateUT();
				}
			}
		}
	}

	private void updateUT() {
		EventCenter.getInstance().fireEvent(new RefreshEvent());
	}

	public List<Endpoint> getEndpoints() {
		List<Endpoint> rst = new LinkedList<Endpoint>();
		for (ZNode node : nodes.values()) {
			rst.addAll(node.getActiveEndpoints());
		}

		return rst;
	}
//	public ZigbeeDevice getDevice(String id)
//	{
//		return devices.get(id);
//	}
	public List<Endpoint> createDummy() {
		ZNode node = new ZNode();
		
		node.setNwkAddress((short)(0));
		node.setIeeeAddress(new byte[8]);
		nodes.put(node.getNwkAddress(), node);
		List<Endpoint> rst = new LinkedList<Endpoint>();
		Endpoint e = new Endpoint(node, (byte)12, this);
		e.setProfileId(HAConstants.ZCL_HA_PROFILE_ID);

		e.setDeviceId(HAConstants.ZCL_HA_DEVICEID_ON_OFF_LIGHT);
		GeneralDevice device = e.createDevice();
		node.getActiveEndpoints().add(e);
		
		deviceAdded(device);
		 e = new Endpoint(node, (byte)13, this);
		 e.setProfileId(HAConstants.ZCL_HA_PROFILE_ID);

			e.setDeviceId(HAConstants.ZCL_HA_DEVICEID_HEATING_COOLING_UNIT);
			device = e.createDevice();
			node.getActiveEndpoints().add(e);
			
			deviceAdded(device);
			
			 e = new Endpoint(node, (byte)14, this);

				e.setProfileId(HAConstants.ZCL_HA_PROFILE_ID);
				e.setDeviceId(HAConstants.ZCL_HA_DEVICEID_SHADE);
				device = e.createDevice();
				node.getActiveEndpoints().add(e);
				
				deviceAdded(device);
				
				e = new Endpoint(node, (byte)15, this);
//				e.setName("�����ҵ�");
				e.setProfileId(HAConstants.ZCL_HA_PROFILE_ID);
				e.setDeviceId(HAConstants.ZCL_HA_DEVICEID_ON_OFF_LIGHT);
				device = e.createDevice();
				node.getActiveEndpoints().add(e);
				
				deviceAdded(device);
				
				 e = new Endpoint(node, (byte)16, this);
//					e.setName("�����ҿյ�");
					e.setProfileId(HAConstants.ZCL_HA_PROFILE_ID);
					e.setDeviceId(HAConstants.ZCL_HA_DEVICEID_HEATING_COOLING_UNIT);
					device = e.createDevice();
					node.getActiveEndpoints().add(e);
					
					deviceAdded(device);
					
					e = new Endpoint(node, (byte)17, this);
//					e.setName("���ȵ�");
					e.setProfileId(HAConstants.ZCL_HA_PROFILE_ID);
					e.setDeviceId(HAConstants.ZCL_HA_DEVICEID_ON_OFF_LIGHT);
					device = e.createDevice();
					node.getActiveEndpoints().add(e);
					
					deviceAdded(device);
					e = new Endpoint(node, (byte)18, this);
					
					e = new Endpoint(node, (byte)20, this);
//					e.setName("ѹ����");
					e.setProfileId(HAConstants.ZCL_HA_PROFILE_ID);
					e.setDeviceId(HAConstants.ZCL_HA_DEVICEID_PRESSURE_SENSOR);
					device = e.createDevice();
					node.getActiveEndpoints().add(e);
					
					deviceAdded(device);
					e = new Endpoint(node, (byte)18, this);
					
					e.setDeviceId(HAConstants.ZCL_HA_DEVICEID_DIMMABLE_LIGHT);
					e.setProfileId(HAConstants.ZCL_HA_PROFILE_ID);
					device = e.createDevice();
					node.getActiveEndpoints().add(e);
					
					deviceAdded(device);
		return rst;
	}
	public List<Endpoint> getEndpointsSupport(short cluster) {
		List<Endpoint> rst = new LinkedList<Endpoint>();
		for (ZNode node : nodes.values()) {
			for (Endpoint e : node.getActiveEndpoints())
				if (e.getInClusters().contains(cluster))
					rst.add(e);

		}

		return rst;
	}
	public List<GeneralDevice> getDevicesSupport(short cluster) {
		List<GeneralDevice> rst = new LinkedList<GeneralDevice>();
		for (ZNode node : nodes.values()) {
			for (Endpoint e : node.getActiveEndpoints())
				if (e.getInClusters().contains(cluster))
					rst.add(e.getDevice());

		}

		return rst;
	}
	public List<GeneralDevice> getDevicesProfile(short profile) {
		List<GeneralDevice> rst = new LinkedList<GeneralDevice>();
		for (ZNode node : nodes.values()) {
			for (Endpoint e : node.getActiveEndpoints())
				if (e.getProfileId() == profile && e.getDevice() != null)
					rst.add(e.getDevice());

		}

		return rst;
	}
	public List<Endpoint> getEndpointsProfile(short profile) {
		List<Endpoint> rst = new LinkedList<Endpoint>();
		for (ZNode node : nodes.values()) {
			for (Endpoint e : node.getActiveEndpoints())
				if (e.getProfileId() == profile)
					rst.add(e);

		}

		return rst;
	}
	public List<Endpoint> getControlledEndpointsProfile(short profile) {
		List<Endpoint> rst = new LinkedList<Endpoint>();
		for (ZNode node : nodes.values()) {
			for (Endpoint e : node.getActiveEndpoints())
				if (e.getProfileId() == profile/* && !e.getInClusters().isEmpty()*/)
					rst.add(e);

		}

		return rst;
	}
	public short nextGroupId() {
		for (int i = 0; i < 0xffff; i++) {
			short j = (short) i;
			if (groups.get(j) == null)
				return j;
		}
		throw new RuntimeException("");
	}

	public byte nextSceneId() {
		for (int i = 0; i < 0xff; i++) {
			byte j = (byte) i;
			if (scenes.get(j) == null)
				return j;
		}
		throw new RuntimeException("");
	}
//	public GeneralDevice getRemoteControlled(){
//		GeneralDevice gd = new GeneralDevice();
//		gd.setFixedType(false);
//		gd.setName("�Ҿ�");
//		gd.setType("home");
//		Map<String, DeviceComponent> cs = new HashMap<String, DeviceComponent>();
//		List<Endpoint> eps = this.getControlledEndpointsProfile(HAConstants.ZCL_HA_PROFILE_ID);
//		for(Endpoint ep : eps){
//			ZigbeeDevice zd = ep.getDevice();
//			if(zd == null)
//				continue;
//			if(zd.getConfig().isExport()){
//				DeviceComponent dc = new DeviceComponent();
//				short profile = zd.getEndpoint().getProfileId();
//				short deviceId = zd.getEndpoint().getDeviceId();
//				String lid = DataUtil.hex(zd.getEndpoint().getParent().getIeeeAddress()) 
//				+ DataUtil.hex(zd.getEndpoint().getEndpointId());
//				String ct = DataUtil.hex(profile) + DataUtil.hex(deviceId);
//				dc.setComponentType(ct);
//				dc.setLocalId(lid);
//				dc.setName(zd.getName());
//				cs.put(lid
//						, dc);
//			}
//		}
//		gd.setComponents(cs);
//		
//		
//		
//		//gd.setId()
//		//id="communication identifier" name="�Ҿ�" ownerId="owner identifier" type="home" fixedType="false" supportedChannel="[sip]">
//
//		return gd;
//	}

	public ZigbeeDevice getDevice(String toComponent) {
		String ieee = toComponent.substring(0, 16);
		String eid = toComponent.substring(16);
		
	
		ZNode node = getNode(ieee);
		if(node == null)
			return null;
		Endpoint ed = node.getEndPoint(eid);
		if(ed == null)
			return null;
		return ed.getDevice();
		
		
	}

	public void refresh() {
		this.nodes.clear();
		this.groups.clear();
		this.scenes.clear();
		MtCommand r = RequestFactory.MtIEEEAddrRequest((short)0x00, (byte)0, (byte)1);
		RequestQueue.offer(r);
		
	}

//	public GeneralDevice defination() {
//		// TODO Auto-generated method stub
//		return this.getRemoteControlled();
//	}

	public DeviceManager getDeviceManager() {
		// TODO Auto-generated method stub
		return this.deviceManager;
	}

	public GroupManager getGroupManager() {
		// TODO Auto-generated method stub
		return groupManager;
	}

	public SceneManager getSceneManager() {
		// TODO Auto-generated method stub
		return sceneManager;
	}



	public void addDeviceListener(DeviceManagementListener listener) {
		deviceListeners.add(listener);
		
	}
	void deviceAdded(GeneralDevice device){
		for(DeviceManagementListener dl : deviceListeners)
			dl.added(device);
	}
}
